home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Scene Storm
/
Scene Storm - Volume 1.iso
/
coding
/
c
/
northc
/
example2.lzh
/
top
/
func.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-08-30
|
5KB
|
257 lines
/* Copyright (c) 1988 by Sozobon, Limited. Author: Tony Andrews
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to redistribute it freely, with the
* following restrictions:
* 1) No charge may be made other than reasonable charges for reproduction.
* 2) Modified versions must be clearly marked as such.
* 3) The authors are not responsible for any harmful consequences
* of using this software, even if they result from defects in it.
*/
#include "top.h"
BLOCK *fhead; /* head of the current function */
/*
* dofunc() - process one function
*
* Returns FALSE on end of file
*/
bool
dofunc()
{
BLOCK *getfunc();
#ifdef DEBUG
if (debug)
fprintf(stderr, "dofunc() - calling getfunc()\n");
#endif
if ((fhead = getfunc()) == NULL)
return FALSE;
/*
* Process the function we just read
*/
bopt(fhead); /* perform branch optimization (must be done first) */
if (do_dflow)
rhealth(fhead); /* perform live/dead register analysis */
if (do_peep)
peep(fhead); /* peephole optimizations */
/*
* Now dump out the modified tree
*/
#ifdef DEBUG
if (debug)
fprintf(stderr, "dofunc() - calling putfunc()\n");
#endif
putfunc(fhead);
#ifdef DEBUG
if (debug)
fprintf(stderr, "dofunc() - calling freesym()\n");
#endif
freesym(); /* free the symbol table */
return TRUE;
}
static bool saw_eof = FALSE;
/*
* getfunc() - get a function and return a pointer to its starting block
*
* Returns NULL on end of file.
*/
BLOCK *
getfunc()
{
#ifdef NORTHC
/* NorthC setting registers to 0 */
BLOCK *head; /* starting block for this function */
BLOCK *ob; /* the last block we read */
#else
register BLOCK *head; /* starting block for this function */
register BLOCK *ob; /* the last block we read */
#endif
register BLOCK *cb; /* the block we're currently reading */
if (saw_eof)
return NULL;
head = NULL;
/*
* Starting a global function
*/
#ifdef NORTHC
if (stricmp(t_op, "XDEF") == 0) {
#else
if (strcmp(t_op, ".globl") == 0) {
#endif
/*
* Enter the symbol and mark it global.
*/
head = mksym(t_arg);
head->flags |= B_GLOBAL;
readline();
}
ob = NULL;
for (;;) {
if (ob == NULL) {
if (t_lab[0] != '_') {
fprintf(stderr, "top: expected function label\n");
exit(EXIT_FAILURE);
}
if (head == NULL)
head = mksym(t_lab);
} else if (t_lab[0] == '\0') {
fprintf(stderr, "top: expected block label\n");
exit(EXIT_FAILURE);
}
if ((cb = getsym(t_lab)) == NULL)
cb = mksym(t_lab);
/*
* The last block falls through to this one.
*/
if (ob != NULL) {
ob->chain = cb;
ob->next = cb;
ob->bfall = cb;
}
t_lab[0] = '\0';
/*
* Now read lines until we hit a new block or another
* function.
*/
for (;;) {
/*
* If we see a global, we're done with the function
*/
#ifdef NORTHC
if (stricmp(t_op, "xdef") == 0)
#else
if (stricmp(t_op, ".globl") == 0)
#endif
return head;
/*
* If we see a function label, we're done too.
*/
if (t_lab[0] == '_')
return head;
/*
* If we see any other label, we're done with the block.
*/
if (t_lab[0])
break;
addinst(cb, t_op, t_arg);
/*
* If we're at EOF, note the we've hit the end of
* file, but return the function we just read.
*/
if (!readline()) {
saw_eof = TRUE;
return head;
}
}
ob = cb;
}
}
/*
* putfunc(sb) - print out the function starting at block 'sb'
*
* The 'next' pointers determine the order in which things are placed
* in the file. Branch instructions have been removed so they need to
* be replaced here on output. Conditional branches are generated if
* indicated (by non-null 'bcond'). Unconditional branches are generated
* at the end of a block if it's "fall through" block isn't going to
* be the next thing in the file.
*/
#ifdef NORTHC
int sNum = 0;
int out_code = 0;
#endif
putfunc(sb)
register BLOCK *sb;
{
register BLOCK *cb;
register INST *ci;
#ifdef NORTHC
if(out_code==0)
fprintf(ofp, "\tSECTION\tFNUM%d,CODE\n",sNum++);
out_code = 1;
fprintf(ofp, ";\n");
fprintf(ofp, "; %s\n", sb->name);
fprintf(ofp, ";\n");
#else
fprintf(ofp, "*\n");
fprintf(ofp, "* %s\n", sb->name);
fprintf(ofp, "*\n");
fprintf(ofp, "\t.text\n");
#endif
for (cb = sb; cb != NULL ;cb = cb->next) {
if (cb->flags & B_GLOBAL)
#ifdef NORTHC
fprintf(ofp, "\tXDEF\t%s\n", cb->name);
#else
fprintf(ofp, "\t.globl\t%s\n", cb->name);
#endif
if (*cb->name == '_')
fprintf(ofp, "%s:\n", cb->name);
else if (cb->flags & B_LABEL)
fprintf(ofp, "%s:\n", cb->name);
#ifdef DEBUG
if (debug) {
#ifdef NORTHC
fprintf(ofp, ";\n");
fprintf(ofp, "; %s, ref:%04x set:%04x\n",
cb->name, cb->rref, cb->rset);
fprintf(ofp, ";\n");
#else
fprintf(ofp, "*\n");
fprintf(ofp, "* %s, ref:%04x set:%04x\n",
cb->name, cb->rref, cb->rset);
fprintf(ofp, "*\n");
#endif
}
#endif
for (ci = cb->first; ci != NULL ;ci = ci->next)
putinst(ci);
/*
* If there's a conditional branch, put out the
* appropriate instruction for it.
*/
if (cb->bcond != NULL && cb->bcode >= 0)
fprintf(ofp, "\t%s\t%s\n",
opnames[cb->bcode], cb->bcond->name);
/*
* If there's a "fall through" label, and the destination
* block doesn't come next, put out a branch.
*/
if (cb->bfall != NULL && cb->bfall != cb->next) {
s_badd++;
fprintf(ofp, "\tbra\t%s\n", cb->bfall->name);
}
}
}